package mil.af.amc.adpetracker.service;

import mil.af.amc.adpetracker.dao.*;
import mil.af.amc.adpetracker.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * Implementation for Hand Receipt Service
 *
 * @author TSgt Ferguson
 */
@Service("handReceiptService")
public class HandReceiptServiceImpl implements HandReceiptService {

    private HandReceiptDao handReceiptDao;

    @Autowired
    public void setHandReceiptDao(HandReceiptDao handReceiptDao) {
        this.handReceiptDao = handReceiptDao;
    }

    private AdpeAccountDao adpeAccountDao;

    @Autowired
    public void setAdpeAccountDao(AdpeAccountDao adpeAccountDao) {
        this.adpeAccountDao = adpeAccountDao;
    }

    private EquipmentItemDao equipmentItemDao;

    @Autowired
    public void setEquipmentItemDao(EquipmentItemDao equipmentItemDao) {
        this.equipmentItemDao = equipmentItemDao;
    }

    private MailSender mailSender;

    @Autowired
    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    private MaintenanceEntryDao maintenanceEntryDao;

    @Autowired
    public void setMaintenanceEntryDao(MaintenanceEntryDao maintenanceEntryDao) {
        this.maintenanceEntryDao = maintenanceEntryDao;
    }

    private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public List<HandReceipt> getAll() {

        return handReceiptDao.getAll();
    }

    public List<HandReceipt> getAllByAdpeAccount(int adpeAccountId) {

        AdpeAccount acct = adpeAccountDao.getById(adpeAccountId);
        return getAllByAdpeAccount(acct);
    }

    public List<HandReceipt> getAllByAdpeAccount(AdpeAccount adpeAccount) {

        return handReceiptDao.getByAdpeAccount(adpeAccount);
    }

    public List<HandReceipt> getAllByUser(int userId) {

        User user = userDao.getById(userId);
        return getAllByUser(user);
    }

    public List<HandReceipt> getAllByUser(User user) {

        return handReceiptDao.getByUser(user);
    }

    public HandReceipt getById(int handReceiptId) {

        return handReceiptDao.getById(handReceiptId);
    }

    public HandReceipt createHandReceipt(Map map) throws ServiceException {

        HandReceipt hr = new HandReceipt();
        // TODO: FIX THE NAME FIELD FOR AUTOGENERATED VALUES!
        String name = (String) map.get("name");
        hr.setName(name);

        int adpeAccountId = (Integer) map.get("adpeAccountId");
        AdpeAccount acct = adpeAccountDao.getById(adpeAccountId);
        hr.setAdpeAccount(acct);

        int custodianId = (Integer) map.get("custodianId");
        User custodian = userDao.getById(custodianId);
        hr.setCustodian(custodian);

        int userId = (Integer) map.get("assignedUserId");
        User assignedUser = userDao.getById(userId);
        hr.setAssignedUser(assignedUser);

        // Issue Date
        String strIssueDate = (String) map.get("issueDate");
        try {
            Date issueDate = new SimpleDateFormat("dd-mmm-yyyy").parse(strIssueDate);
            hr.setIssueDate(issueDate);
        } catch (ParseException e) {
            throw new ServiceException("messages.handreceipt.issuedate.invalid", e);
        }

        // Return Date
        String strReturnDate = (String) map.get("returnDate");
        try {
            Date returnDate = new SimpleDateFormat("dd-mmm-yyyy").parse(strReturnDate);
            hr.setReturnDate(returnDate);
        } catch (ParseException e) {
            throw new ServiceException("messages.handreceipt.returndate.invalid", e);
        }

        // Add Equipment Items to HandReceipt package
        Integer[] pkgitem = (Integer[]) map.get("itemId");
        for (int itemId : pkgitem) {
            EquipmentItem item = equipmentItemDao.getById(itemId);

            // Make sure that the item is not going to be removed from a DRMO or ROS/Waiver package by only allowing
            // Active items to be added to a hand receipt
            if (item.getStatus() != Status.Active) {

                throw new ServiceException("messages.handreceipt.invalid","Cannot assign item to Hand Receipt (Status is not Active)");

            } else {

                item.setStatus(Status.HandReceipt);

                MaintenanceEntry maint = new MaintenanceEntry();
                maint.setEntryDate(new Date());
                maint.setItem(item);
                maint.setEntryText("Item handreceipted to " + assignedUser.getDisplayName());

                item.getMaintenanceEntries().add(maint);
                equipmentItemDao.save(item);
                maintenanceEntryDao.save(maint);
            }
        }
        handReceiptDao.save(hr);

        if (hr.getAssignedUser().getEmail() != null) {
            
            SimpleMailMessage msg = new SimpleMailMessage();
            msg.setTo(assignedUser.getEmail());
            msg.setFrom("ADPE-NOREPLY@scott.af.mil");
            msg.setSubject("Creation of Hand Receipt");

            StringBuilder sb = new StringBuilder();
            sb.append("You have been assigned the following items via Hand Receipt: \r\n");
            sb.append("\r\n");
            sb.append("Serial                Description");
            sb.append("------------------------------------------------");

            for(EquipmentItem item: hr.getIdentifiedItems()) {
                sb.append(item.getSerial() + "             " + item.getDescription() + "\r\n");
            }

            if (hr.getReturnDate() != null) {
                sb.append("These items need to be returned by " + hr.getReturnDate());
            }

            sb.append("If this information is in error, please contact " + custodian.getDisplayName());

            msg.setText(sb.toString());

            mailSender.send(msg);
        }

        hr = handReceiptDao.getByName(name);
        return hr;


    }

    public HandReceipt editHandReceipt(Map map) throws ServiceException {
        throw new UnsupportedOperationException();
    }

    public void deleteHandReceipt(int handReceiptId) throws ServiceException {

        HandReceipt hr = handReceiptDao.getById(handReceiptId);

        // If any items are on the hand receipt, set them free
        if (hr.getIdentifiedItems().size() > 0) {
            for (EquipmentItem item: hr.getIdentifiedItems()) {

                item.setStatus(Status.Active);

                MaintenanceEntry maint = new MaintenanceEntry();
                maint.setEntryDate(new Date());
                maint.setEntryText("Item removed from hand receipt " + hr.getName());
                maint.setItem(item);

                item.getMaintenanceEntries().add(maint);
                equipmentItemDao.save(item);
                maintenanceEntryDao.save(maint);

            }
        }

        if (hr.getAssignedUser().getEmail() != null) {
            SimpleMailMessage msg = new SimpleMailMessage();
            msg.setTo(hr.getAssignedUser().getEmail());
            msg.setFrom("ADPE-NOREPLY@scott.af.mil");
            msg.setSubject("Cancellation of Hand Receipt");

            StringBuilder sb = new StringBuilder();
            sb.append("Hand Receipt " + hr.getName() + " has been closed and deleted. You no longer have the items from" +
                    "this receipt assigned to you. \r\n");
            msg.setText(sb.toString());

            mailSender.send(msg);
        }

        handReceiptDao.delete(hr);
    }

    public void closeHandReceipt(int handReceiptId) throws ServiceException {

        deleteHandReceipt(handReceiptId);

    }
}
